package com.topnav.mc.admin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.js.lib.exception.CustomException;
import com.topnav.mc.admin.dao.mapper.AuthorizationMapper;
import com.topnav.mc.admin.entity.Authorization;
import com.topnav.mc.admin.entity.Device;
import com.topnav.mc.admin.entity.Organization;
import com.topnav.mc.admin.entity.RoleAuthorization;
import com.topnav.mc.admin.entity.bean.AuthorizationBean;
import com.topnav.mc.admin.entity.param.AuthorizationParam;
import com.topnav.mc.admin.service.IAuthorizationService;
import com.topnav.mc.admin.service.IRoleAuthorizationService;
import com.topnav.mc.base.mc.McServiceImpl;
import com.topnav.mc.exception.ExceptionMsg;
import com.topnav.mc.uitls.ExceptionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @Author: kenny
 * @Date: 2024/2/27 10:04
 */
@Service
public class AuthorizationServiceImpl extends McServiceImpl<AuthorizationMapper, Authorization,
        AuthorizationBean, AuthorizationParam> implements IAuthorizationService {
    @Autowired
    private IRoleAuthorizationService roleAuthorizationService;

    @Override
    public boolean beforeDelete(Authorization entity){
        // 是否有下级
        LambdaQueryWrapper<Authorization> wrapper = new LambdaQueryWrapper<Authorization>().eq(Authorization::getParentId,entity.getId());
        if (this.getOne(wrapper,false) != null){
            //此机构已包含下级，不能删除
            throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_AUTORIZATION_USED_BY_PARENT);
        }
        LambdaQueryWrapper<RoleAuthorization> raWrapper = new LambdaQueryWrapper<RoleAuthorization>().eq(RoleAuthorization::getAuthId,entity.getId());
        if (roleAuthorizationService.getOne(raWrapper,false) != null){
            //此菜单已被设置权限, 不能删除
            throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_AUTORIZATION_USED_BY_ROLE);
        }
        return true;
    }

    /**
     * 检查下级关系冲突,返回true为正确,没有冲突
     * @param parent
     * @param current
     * @return
     */
    private boolean checkEndlessLoop(Authorization parent, Authorization current ){
        boolean result = true;
        if (parent == null){	return result;}
        if (parent.getId() == current.getId()){return false;}


        LambdaQueryWrapper<Authorization> wrapper = new LambdaQueryWrapper<Authorization>().eq(Authorization::getParentId,current.getId());
        List<Authorization> list = this.list(wrapper);
        /** 如果没下级了不再继续检查 */
        if (CollectionUtils.isEmpty(list)){	return result;	}

        for (int i=0;i<list.size();i++){
            if (list.get(i).getId() == parent.getId()){
                result = false;
                break;
            }

            //递归查找
            result = checkEndlessLoop(parent,list.get(i));
            if (result == false){
                return result;
            }
        }
        return result;
    }

    /**
     * 更新父级的是否含子件的标志
     * @param id
     */
    private void updateParentHasChildTag(Long id){
        if (id != null){
            LambdaQueryWrapper<Authorization> wrapper = new LambdaQueryWrapper<Authorization>().eq(Authorization::getParentId,id);
            Authorization temp = this.getOne(wrapper,false);
            LambdaUpdateWrapper<Authorization> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Authorization::getId,id);
            if (temp == null){
                updateWrapper.set(Authorization::getHasChild,false);
            }else{
                updateWrapper.set(Authorization::getHasChild,true);
            }
            this.update(updateWrapper);

/*            //UpdateWrapper<Authorization> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id",id);
            if (temp == null){
                updateWrapper.set("has_child",false);
            }else{
                updateWrapper.set("has_child",true);
            }
            this.update(updateWrapper);*/
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Authorization entity) {

        if (this.getOne(new LambdaQueryWrapper<Authorization>().eq(Authorization::getAtCode,entity.getAtCode()), true) != null){
            throw new CustomException(-1,"菜单编码  %s 已存在",entity.getAtCode());
        }
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        entity.setHasChild(false);


        boolean result = super.save(entity);//SqlHelper.retBool(getBaseMapper().insert(entity));
        if (!result){return result;}

        //更新父级的是否含子件的标志
        this.updateParentHasChildTag(entity.getParentId());

        Long id = entity.getParentId()==null?0L:entity.getParentId();
        Authorization parent = this.getOne(new LambdaQueryWrapper<Authorization>().eq(Authorization::getId,id), false);
        /** 检查冲突*/
        if (!checkEndlessLoop(parent,entity)){
            throw new CustomException(-1,"上级菜单冲突, 先重新选择上级菜单");
        }

        /** 更新 path */
        if(parent != null){
            entity.setAtPath(parent.getAtPath() + entity.getId()+"/");
        }else{
            entity.setAtPath(entity.getId()+"/");
        }
        this.updateById(entity);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(Authorization entity) {
        boolean result = false;
        LambdaQueryWrapper<Authorization> wrapper = new LambdaQueryWrapper<Authorization>()
                .eq(Authorization::getAtCode, entity.getAtCode()).ne(Authorization::getId, entity.getId());
        if (this.getOne(wrapper, false) != null){
            throw new CustomException(-1,"菜单编码  %s 已存在",entity.getAtCode());
        }

        Authorization parent = this.getOne(new LambdaQueryWrapper<Authorization>().eq(Authorization::getId,entity.getParentId()==null?0L:entity.getParentId()), false);
        /** 检查冲突*/
        if (!checkEndlessLoop(parent,entity)){
            throw new CustomException(-1,"上级菜单冲突");
        }

        /** 先保留原数据  */
        Authorization old = this.getById(entity.getId());
        /** 更新 */
        entity.setUpdateTime(new Date());
        result = super.updateById(entity);
        if (!result){return false;}

        if (null == entity.getParentId()) {
            LambdaUpdateWrapper<Authorization> updateWrapper = new LambdaUpdateWrapper<Authorization>();
            updateWrapper.set(Authorization::getParentId, null);
            updateWrapper.eq(Authorization::getId, entity.getId());
            this.update(updateWrapper);
        }

        /** 如果修改了上级，则一起更新 path */
        Long oldParentId = old.getParentId()==null?0L:old.getParentId();
        Long newParentId = entity.getParentId()==null?0L:entity.getParentId();
        if (!oldParentId.equals(newParentId)){
            if (newParentId.equals(0L)){
                entity.setAtPath(entity.getId() + "/");
            }else{
                entity.setAtPath(this.getById(newParentId).getAtPath() + entity.getId() + "/");
            }

            wrapper.clear();
            wrapper.likeRight(Authorization::getAtPath, old.getAtPath());
            List<Authorization> list = this.list(wrapper);
            for (Authorization a : list){
                String path = a.getAtPath().replaceFirst(old.getAtPath(),entity.getAtPath());
                a.setAtPath(path);
            }
            this.updateBatchById(list);
        }
        //更新父级的是否含子件的标志
        this.updateParentHasChildTag(entity.getParentId());
        this.updateParentHasChildTag(old.getParentId());
        return true;
    }
}
